package com.hahehiho.myalbum;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.common.ByteOrder;
import org.apache.commons.imaging.common.IImageMetadata;
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata.GPSInfo;
import org.apache.commons.imaging.formats.tiff.constants.AllTagConstants;
import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
import org.apache.commons.imaging.formats.tiff.fieldtypes.FieldType;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfo;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;

public class ImageFileHandler {
	
	private static TiffImageMetadata getMetaData(File file) {
		IImageMetadata meta = null;
		try {
			meta = Imaging.getMetadata(file);
		} catch (ImageReadException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
		
		if(meta == null)
			return null;

		TiffImageMetadata exif = null;
		if (meta instanceof JpegImageMetadata) {
			exif = ((JpegImageMetadata) meta).getExif();
		} else if (meta instanceof TiffImageMetadata) {
			exif = (TiffImageMetadata) meta;
		} else {
			System.out.println(exif.getClass());
			return null;
		}
		
		return exif;
	}

	public static MyAlbumVO readMyAlbumVO(File file) {
		
		MyAlbumVO vo = new MyAlbumVO();
		vo.setFilePath(file.getAbsolutePath());
		Calendar cal = Calendar.getInstance();
		Date zero = new Date();
		zero.setTime(0);;
		cal.setTimeInMillis(zero.getTime());
		vo.setOrgDate(cal);
		
		TiffImageMetadata exif = ImageFileHandler.getMetaData(file);
		if(exif == null)
			return vo;
		
		try {
			String value = (String) exif.getFieldValue(AllTagConstants.EXIF_TAG_XPTITLE);
			vo.setXpTitle(value);
		} catch (ImageReadException e) {
		}

		try {
			String value = (String) exif.getFieldValue(AllTagConstants.EXIF_TAG_XPSUBJECT);
			vo.setXpSubject(value);
		} catch (ImageReadException e) {
		}

		try {
			String value = (String) exif.getFieldValue(AllTagConstants.EXIF_TAG_XPKEYWORDS);
			vo.setXpKeywords(value);
		} catch (ImageReadException e) {
		}

		try {
			String value = (String) exif.getFieldValue(AllTagConstants.EXIF_TAG_XPCOMMENT);
			vo.setXpComment(value);
		} catch (ImageReadException e) {
		}

		
		try {
			GPSInfo value = exif.getGPS();
			if(value != null) {
				vo.setLatitude(value.getLatitudeAsDegreesNorth());
				vo.setLongitude(value.getLongitudeAsDegreesEast());
				vo.setIsGPS(true);
			}
		} catch (ImageReadException e) {
		}		
		
		try {
			String value[] = exif.getFieldValue(AllTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
			if(value != null && value.length > 0) {	
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
				try {
					cal.setTime(sdf.parse(value[0]));
				} catch (ParseException e) {
				}
			}
			vo.setOrgDate(cal);
		} catch (ImageReadException e) {
		}

		
		return vo;
	}
	
	public static void main(String[] args) {
		MyAlbumVO vo = ImageFileHandler.readMyAlbumVO(new File("C:\\temp\\IMG_0217.new.JPG"));
		System.out.println(vo);
	}

	public static boolean modifyMyAlbumVO(MyAlbumVO vo) {
		boolean isSuccess = false;
		
		TiffImageMetadata exif = ImageFileHandler.getMetaData(new File(vo.getFilePath()));
		if(exif == null)
			return false;
		
		String tempFilePath = vo.getFilePath() + ".tmp";
		
		BufferedOutputStream os = null;
		try {
			TiffOutputSet outputSet = null;

			outputSet = exif.getOutputSet();
			if (null == outputSet) {
				outputSet = new TiffOutputSet();
			}

			
			outputSet.setGPSInDegrees(vo.getLongitude(), vo.getLatitude());
			

			TiffOutputDirectory exifDir = outputSet.getOrCreateRootDirectory();
			updateRootDirectoryField(exifDir, AllTagConstants.EXIF_TAG_XPTITLE, FieldType.BYTE , vo.getXpTitle());
			updateRootDirectoryField(exifDir, AllTagConstants.EXIF_TAG_XPKEYWORDS, FieldType.BYTE, vo.getXpKeywords());
			updateRootDirectoryField(exifDir, AllTagConstants.EXIF_TAG_XPSUBJECT, FieldType.BYTE, vo.getXpSubject());
			updateRootDirectoryField(exifDir, AllTagConstants.EXIF_TAG_XPCOMMENT, FieldType.BYTE, vo.getXpComment());

			SimpleDateFormat sdf = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
			String odate = sdf.format(vo.getOrgDate().getTime());
			
			exifDir = outputSet.getOrCreateExifDirectory();
			exifDir.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
			TiffOutputField field = new TiffOutputField(AllTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, FieldType.ASCII, odate.length(), odate.getBytes());
			exifDir.add(field);


			os = new BufferedOutputStream(new FileOutputStream(new File(tempFilePath)));

			new ExifRewriter().updateExifMetadataLossy(new File(vo.getFilePath()), os, outputSet);

			os.close();
			os = null;
			
			new File(vo.getFilePath()).delete();
			new File(tempFilePath).renameTo(new File(vo.getFilePath()));
			new File(tempFilePath).delete();
			System.out.println("success save to file " + vo.getFilePath());
			
			isSuccess = true;
		} catch (ImageWriteException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (ImageReadException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (final IOException e) {

				}
			}
		}				
		
		
		return isSuccess;
	}
	
	private static void updateRootDirectoryField(TiffOutputDirectory exifDir, TagInfo exifTag, FieldType fieldType, String value) {
		TiffOutputField field = exifDir.findField(exifTag);
		System.out.println(field);
		if(field != null)
			exifDir.removeField(exifTag);

		byte[] encodedValue = null;
		try {
			encodedValue = exifTag.encodeValue(fieldType, (Object) value, ByteOrder.NETWORK);
		} catch (ImageWriteException e) {
			e.printStackTrace();
		}
		
		field = new TiffOutputField(exifTag, fieldType, encodedValue.length, encodedValue);
		exifDir.add(field);
		System.out.println(field);		
	}

}
